﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace AudioPlayer.GUI {
	internal class Round {
		#region Variables
		private Rectangle _bounds;
		private Size _arcSize;
		private RoundType _type;//0 - all, 1 - only top, 2 - only bottom,3 - No round, borders from side

		private IList<Rectangle> _pie;
		private IList<Rectangle> _back;
		private IList<Point> _pointA;
		private IList<Point> _pointB;
		private IList<int> _startAngle;
		private IList<int> _sweapAngle;
		
		#endregion
		#region Constructor
		public Round() {
			Init(Rectangle.Empty, Size.Empty, RoundType.All);
		}
		public Round(Rectangle bounds, RoundType type) {
			Init(bounds, new Size(8, 8), type);
		}
		public Round(Rectangle bounds, Size arcSize) {
			Init(bounds,arcSize,RoundType.All);
		}
		public Round(Rectangle bounds, Size arcSize, RoundType type) {
			Init(Bounds, arcSize,type);
		}
		#endregion
		#region Private Voids
		private void Init(Rectangle bounds,Size arcSize,RoundType type) {
			_bounds = bounds;
			_arcSize = arcSize;
			_type = type;

			_pie = new List<Rectangle>(4);
			_back = new List<Rectangle>(3);
			_pointA = new List<Point>(4);
			_pointB = new List<Point>(4);
			_startAngle = new List<int>(4);
			_sweapAngle = new List<int>(4);

			Generate();
		}
		private void Clear() {
			_pie.Clear();
			_back.Clear();
			_pointA.Clear();
			_pointB.Clear();
			_startAngle.Clear();
			_sweapAngle.Clear();
		}
		private void Generate() {
			this.Clear();
			this.GenerateBorder();
			this.GenerateBackground();
		}
		private void GenerateBorder() {
			switch (_type) {
				case  RoundType.All://Full
					AddRoundAll();
					AddBorderTopHalf();
					AddBorderBottomHalf();
					AddBorderRightHalf();
					AddBorderLeftHalf();
					break;
				case RoundType.Top://Top
					AddRoundTop();
					AddBorderTopHalf();
					//AddBorderBottomFull();
					AddBorderLeftTop();
					AddBorderRightTop();
					break;
				case RoundType.Bottom://Bottom
					AddRoundBottom();
					//AddBorderTopFull();
					AddBorderBottomHalf();
					AddBorderLeftBottom();
					AddBorderRightBottom();
					break;
				case RoundType.Middle://Middle
					AddBorderLeftFull();
					AddBorderRightFull();
					break;
				case RoundType.OnlyRight:
					AddRoundTopRight();
					AddRoundBottomRight();
					//AddBorderLeftFull();
					AddBorderTopRight();
					AddBorderBottomRight();
					AddBorderRightHalf();
					break;
			}
		}
		private void GenerateBackground() {
			switch (_type) {
				case RoundType.All:
					AddBackMiddle();
					AddBackLeftMiddle();
					AddBackRightMiddle();

					AddBackTopHalf();
					AddBackBottomHalf();
					break;
				case RoundType.Top://Top
					AddBackMiddle();
					AddBackTopHalf();
					AddBackBottomFull();
					AddBackLeftMiddle();
					AddBackRightMiddle();
					break;
				case RoundType.Bottom://Bottom
					AddBackMiddle();
					AddBackTopFull();
					AddBackBottomHalf();
					AddBackLeftMiddle();
					AddBackRightMiddle();
					break;
				case RoundType.Middle:
					AddBackFull();
					break;
				case RoundType.OnlyRight:
					AddBackMiddle();
					AddBackRightMiddle();
					AddBackTopHalf();
					AddBackBottomHalf();
					AddBackLeftMiddle();
					AddBackLeftFull();
					break;
			}
		}

		private void AddBorderTopFull() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Y));
		}
		private void AddBorderTopHalf() {
			_pointA.Add(new Point(_bounds.X + _arcSize.Width / 2, _bounds.Y));
			_pointB.Add(new Point(_bounds.Right - 1 - _arcSize.Width / 2, _bounds.Y));
		}
		private void AddBorderTopRight() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y));
			_pointB.Add(new Point(_bounds.Right - _arcSize.Width/2, _bounds.Y));
		}
		private void AddBorderBottomFull() {
			_pointA.Add(new Point(_bounds.X, _bounds.Bottom - 1));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Bottom - 1));
		}
		private void AddBorderBottomHalf() {
			_pointA.Add(new Point(_bounds.X+_arcSize.Width/2, _bounds.Bottom - 1));
			_pointB.Add(new Point(_bounds.Right - 1-_arcSize.Width/2, _bounds.Bottom - 1));
		}
		private void AddBorderBottomRight() {
			_pointA.Add(new Point(_bounds.X, _bounds.Bottom-1));
			_pointB.Add(new Point(_bounds.Right - _arcSize.Width / 2, _bounds.Bottom-1));
		}
		private void AddBorderLeftFull() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y));
			_pointB.Add(new Point(_bounds.X, _bounds.Bottom - 1));
		}
		private void AddBorderLeftHalf() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y + _arcSize.Height / 2));
			_pointB.Add(new Point(_bounds.X,_bounds.Bottom-1-_arcSize.Height/2));
		}
		private void AddBorderLeftTop() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y+_arcSize.Height/2));
			_pointB.Add(new Point(_bounds.X, _bounds.Bottom - 1));
		}
		private void AddBorderLeftBottom() {
			_pointA.Add(new Point(_bounds.X, _bounds.Y));
			_pointB.Add(new Point(_bounds.X, _bounds.Bottom - 1 - _arcSize.Height / 2));
		}
		private void AddBorderRightFull() {
			_pointA.Add(new Point(_bounds.Right - 1, _bounds.Y));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Bottom - 1));
		}
		private void AddBorderRightHalf() {
			_pointA.Add(new Point(_bounds.Right - 1, _bounds.Y + _arcSize.Height / 2));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Bottom - 1 - _arcSize.Height / 2));
		}
		private void AddBorderRightTop() {
			_pointA.Add(new Point(_bounds.Right-1, _bounds.Y + _arcSize.Height / 2));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Bottom - 1));
		}
		private void AddBorderRightBottom() {
			_pointA.Add(new Point(_bounds.Right - 1, _bounds.Y));
			_pointB.Add(new Point(_bounds.Right - 1, _bounds.Bottom - 1 - _arcSize.Height / 2));
		}
		
		private void AddRoundTopLeft() {
			_pie.Add(new Rectangle(_bounds.X, _bounds.Y, _arcSize.Width, _arcSize.Height));
			_startAngle.Add(180);
			_sweapAngle.Add(90);
		}
		private void AddRoundTopRight() {
			_pie.Add(new Rectangle(_bounds.Right - 1 - _arcSize.Width, _bounds.Y, _arcSize.Width, _arcSize.Height));
			_startAngle.Add(270);
			_sweapAngle.Add(90);
		}
		private void AddRoundBottomLeft() {
			_pie.Add(new Rectangle(_bounds.X, _bounds.Bottom - 1 - _arcSize.Height, _arcSize.Width, _arcSize.Height));
			_startAngle.Add(90);
			_sweapAngle.Add(90);
		}
		private void AddRoundBottomRight() {
			_pie.Add(new Rectangle(_bounds.Right - 1 - _arcSize.Width, _bounds.Bottom - 1 - _arcSize.Height, _arcSize.Width, _arcSize.Height));
			_startAngle.Add(0);
			_sweapAngle.Add(90);
		}
		private void AddRoundAll() {
			this.AddRoundTop();
			this.AddRoundBottom();
		}
		private void AddRoundTop() {
			this.AddRoundTopLeft();
			this.AddRoundTopRight();


		}
		private void AddRoundBottom() {
			this.AddRoundBottomLeft();
			this.AddRoundBottomRight();
		}

		private void AddBackFull() {
			_back.Add(new Rectangle(_bounds.X,_bounds.Y,_bounds.Width,_bounds.Height));
		}
		private void AddBackTopFull() {
			_back.Add(new Rectangle(_bounds.X, _bounds.Y, _bounds.Width, _arcSize.Height));
		}
		private void AddBackTopHalf() {
			_back.Add(new Rectangle(_bounds.X+_arcSize.Width/2, _bounds.Y, _bounds.Width-_arcSize.Width, _arcSize.Height/2));
		}
		private void AddBackBottomFull() {
			_back.Add(new Rectangle(_bounds.X, _bounds.Bottom-_arcSize.Height/2, _bounds.Width, _arcSize.Height/2));
		}
		private void AddBackBottomHalf() {
			_back.Add(new Rectangle(_bounds.X+_arcSize.Width/2, _bounds.Bottom-_arcSize.Height/2, _bounds.Width-_arcSize.Width, _arcSize.Height/2));
		}
		private void AddBackMiddle() {
			_back.Add(new Rectangle(_bounds.X + (_arcSize.Width / 2), _bounds.Y + (_arcSize.Height / 2), _bounds.Width - _arcSize.Width, _bounds.Height - _arcSize.Height));
		}
		private void AddBackLeftMiddle() {
			_back.Add(new Rectangle(_bounds.X, _bounds.Y + _arcSize.Height / 2, _arcSize.Width / 2, _bounds.Height - _arcSize.Height));
		}
		private void AddBackLeftFull() {
			_back.Add(new Rectangle(_bounds.X, _bounds.Y, _arcSize.Width / 2, _bounds.Height));
		}
		private void AddBackRightMiddle() {
			_back.Add(new Rectangle(_bounds.Right-_arcSize.Width/2, _bounds.Y + _arcSize.Height / 2,_bounds.Right-1- _arcSize.Width / 2, _bounds.Height - _arcSize.Height));
		}
		#endregion
		#region Public Voids
		
		public void Generate(Rectangle bounds, RoundType type) {
			_bounds = bounds;
			_type = type;
			Generate();
		}
		public void Generate(Rectangle bounds, Size arcSize, RoundType type) {
			_bounds = bounds;
			_arcSize = arcSize;
			_type = type;
		}
		#endregion
		#region Property
		public Rectangle Bounds {
			get { return _bounds; }
			set {
				if (_bounds != value) {
					_bounds = value;
				}
			}
		}
		public RoundType Type {
			get { return _type; }
			set {
				if (value != _type) {
					_type = value;
					Generate();
				}
			}
		}
		public Size ArcSize {
			get { return _arcSize; }
			set {
				if (_arcSize != value) {
					_arcSize = value;
					Generate();
				}
			}
		}
		public IList<Rectangle> Pie {
			get { return _pie; }
		}
		public IList<Rectangle> Back {
			get { return _back; }
		}
		public IList<int> StartAngle {
			get { return _startAngle; }
		}
		public IList<int> SweapAngle {
			get { return _sweapAngle; }
		}
		public IList<Point> PointA {
			get { return _pointA; }
		}
		public IList<Point> PointB {
			get { return _pointB; }
		}
		#endregion
	}
	internal enum RoundType {
		All = 0,
		Top = 1,
		Bottom =2,
		Middle = 3,
		OnlyRight = 4
	}
}